package com.bing.java.synchronizeds;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * @author bing
 *
 * 2019年11月9日 上午10:33:20
 * 
 * 同步一个代码块
 * 它只作用于同一个对象，如果调用两个对象上的同步代码块，就不会进行同步。
        对于以下代码，使用 ExecutorService 执行了两个线程，由于调用的是同一个对象的同步代码块，因此这两个线程会进行同步，当一个线程进入同步语句块时，另一个线程就必须等待。
 */
public class SynchronizedExample {

	public void func1() {
		synchronized (this) {
			for (int i = 0; i < 10; i++) {
				System.out.print(i + " ");
			}
		}
	}

	/**
	 * 2. 同步一个方法
	 * 它和同步代码块一样，作用于同一个对象。
	 */
	public synchronized void func () {
	    // ...
	}
	
	
	/**
	 * 方法内加锁同步一个对象。一个对象进入线程执行，另外一个线程必须等待执行完之后再执行
	 * 结果
	 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 
	 * @param args
	 */
//	public static void main(String[] args) {
//		SynchronizedExample e1 = new SynchronizedExample();
//		ExecutorService executorService = Executors.newCachedThreadPool();
//		executorService.execute(() -> e1.func1());
//		executorService.execute(() -> e1.func1());
//	}
	
	
	/**
	 * 两个线程调用了不同对象的同步代码块，因此这两个线程就不需要同步。从输出结果可以看出，两个线程交叉执行。
	 * @param args
	 */
	public static void main(String[] args) {
	    SynchronizedExample e1 = new SynchronizedExample();
	    SynchronizedExample e2 = new SynchronizedExample();
	    ExecutorService executorService = Executors.newCachedThreadPool();
	    executorService.execute(() -> e1.func1());
	    executorService.execute(() -> e2.func1());
	    
	}
}
